home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / PAS_0693 / RKEYINT.TXT < prev    next >
Text File  |  1993-06-28  |  12KB  |  273 lines

  1. ─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  2. Msg  : 425 of 474                                                               
  3. From : Lou Duchez                          1:157/200.0          21 Jun 93  21:16 
  4. To   : Ian Lin                                                                   
  5. Subj : Using esc key                                                          
  6. ────────────────────────────────────────────────────────────────────────────────
  7. Since you seem to be talking about multiple key presses, let me repost:
  8.  
  9. HOW TO RESET YOUR KEYBOARD INTERRUPT TO READ MULTIPLE KEYS
  10.  
  11. - by Lou DuChez
  12.  
  13. When you press/release a key on the keyboard, the "scan code" of the key
  14. is sent to port 60h of your machine (bit 0-6 specify the key; bit 7
  15. indicates a "press" with a "0" and a release with a "1").  This triggers
  16. hardware interrupt 09h, which triggers other software interrupts and
  17. puts the appropriate keystrokes into your keyboard buffer.  Ideally, 
  18. you'd like to be able to read port 60h directly to get keyboard status, 
  19. but unfortunately the port is reinitialized to "0" in the course of all
  20. those interrupts.  So what you need to do is modify the hardware
  21. interrupt to record which keys are up/down before any of the
  22. "housekeeping" can occur. 
  23.  
  24. To do this, the steps you'll need to do are:
  25.  
  26. 1)  Store the location of the "normal" interrupt 09h routine.  Declare a
  27.     pointer variable called "OLDKBDINT", and execute this command:
  28.  
  29.       getintvec($09, oldkbdint);  { make sure you've got "Uses DOS"! }
  30.  
  31.  
  32. 2)  Write a simple interrupt handler.  Just something to keep track of
  33.     what keys are down.  We'll keep track of them all with an
  34.     "array [0..127] of boolean" called "KeyDown".  Declare this array,
  35.     and be sure to initialize it to all "false" before using it.  (At
  36.     the end of this message, I'll list the various "scan codes" for the
  37.     various keys.  Be patient.)  Here's the new keyboard handler:
  38.  
  39.       procedure newkbdint; interrupt;
  40.       begin
  41.         keydown[port[$60] mod 128] := (port[$60] < 128);
  42.         runproc(oldkbdint);
  43.         mem[$0040:$001a] := mem[$0040:$001c];
  44.         inline($fb);
  45.         end;
  46.  
  47.     Explanations:
  48.     
  49.     - The directive "Interrupt" is necessary so that the compiler
  50.       processes this procedure properly.
  51.     
  52.     - The "KeyDown" line: whichever key is specified in the keyboard
  53.       port, is "pressed" if the high bit is "0" and "released" if the
  54.       high bit is "1".
  55.     
  56.     - RunProc: After reading the port, we want to process the keystroke
  57.       in the "normal" way.  So we "run" the "normal" keyboard interrupt
  58.       routine via "RunProc".  RunProc is a procedure that I cribbed from
  59.       "Turbo Pascal 6.0: The Complete Reference" by Stephen O'Brien, and
  60.       you really need it.  Anyway, it goes like this:
  61.       
  62.         procedure runproc(proctorun: pointer);
  63.         begin
  64.           inline($9c/           { PUSHF }
  65.                  $ff/$5e/$06);  { CALL DWORD PTR [BP+6] }
  66.           end;
  67.  
  68.     - The "Mem" line clears the keyboard buffer.  The one memory
  69.       location points to the first unread character in the buffer, and
  70.       the other points to the very last one.  By setting them equal,
  71.       the computer is fooled into thinking that the keystroke has been
  72.       read.  (This way, your computer won't beep incessantly after 16
  73.       keystrokes.)
  74.     
  75.     - InLine: I'm calling the STI instruction ("Set Interrupt Flag") to
  76.       make sure the system will be able to read hardware interrupts.
  77.       (Not that I turned it "off" anywhere, but a little paranoia never
  78.       hurt anyone ...)
  79.     
  80.     Notice that I don't do much in my interrupt handler except play with
  81.     memory.  That makes it a pretty "crash-proof" animal.  Notice also
  82.     that "my" routine executes first, reading the port before that info
  83.     can be lost; then, after the "normal" interrupt has had its fun, I
  84.     do the "postprocessing" of clearing the keyboard buffer.
  85.  
  86.  
  87. 3)  To invoke this new interrupt handler:
  88.  
  89.       setintvec($09, addr(newkbdint));
  90.       inline($fb);  { another STI for good luck }
  91.  
  92.  
  93. 4)  To reset the old interrupt handler when you end your program:
  94.  
  95.       setintvec($09, oldkbdint);
  96.       inline($fb);  { yet another STI: couldn't hurt, right? }
  97.      * * * C O N T I N U E D   T O   N E X T   M E S S A G E * * *
  98. ---
  99.  * KingQWK 1.00 * As-Easy-As - the ONLY spreadsheet - download it today!
  100. --- FidoPCB v1.4 beta
  101.  * Origin: PC-OHIO - The Best BBS in America (pcohio.com) (1:157/200)
  102.  
  103. ─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  104. Msg  : 426 of 474                                                               
  105. From : Lou Duchez                          1:157/200.0          21 Jun 93  21:16 
  106. To   : Ian Lin                                                                   
  107. Subj : Using esc key         {2}                                              
  108. ────────────────────────────────────────────────────────────────────────────────
  109.      * * * C O N T I N U E D   F R O M   L A S T   M E S S A G E * * *
  110.  
  111.  
  112.  
  113. Congratulations, you now have a new keyboard handler.  The whole animal
  114. should look something like this:
  115.  
  116.  
  117. Program FlamingCarrotRules;
  118. uses Dos;
  119. var keydown: array [0..127] of boolean;
  120.     oldkbdint: pointer;
  121.     cnter: byte;  { just a dumb "counter" variable }
  122.  
  123. {$F+}             { Far calls for this "interrupt" stuff! }
  124.  
  125. procedure runproc();
  126.   .
  127.   .
  128.  
  129. procedure newkbdint; interrupt;
  130.   .
  131.   .
  132.  
  133. begin { main program }
  134.   for cnter := 0 to 127 do keydown[cnter] := false;
  135.   getintvec($09, oldkbdint);
  136.   setintvec($09, addr(newkbdint));
  137.   inline($fb);
  138.     .
  139.     . { Your code goes here; instead of reading the keyboard buffer, }
  140.     . { you check what keys are down via "KeyDown". }
  141.     .
  142.   setintvec($09, oldkbdint);
  143.   inline($fb);
  144.   end.
  145.  
  146.  
  147. All of this makes a very nice unit, by the way.  (Just don't try to
  148. install the "new" interrupt in the initialization part of the unit: the
  149. system doesn't like that.)
  150.  
  151. Another point to consider: a "Ctrl-Break" could cause your program to
  152. pop to DOS before you have a chance to restore the "normal" keyboard
  153. handler.  Bad juju all around.  Two approaches: 1) use CRT and set
  154. "CheckBreak" to false; or 2) write an interrupt handler for "Ctrl-Break"
  155. (interrupt 1bh).  I leave it up to you to set it up.  (Hint: it's very
  156. much like the above, except that your new handler should contain NO
  157. instructions -- so the system does NOTHING on a "Ctrl-Break" -- except
  158. maybe another STI ...)
  159.  
  160. Finally, the scan codes (so you can actually make heads or tails of
  161. "KeyDown").  First some constants for "special" keys.
  162.  
  163. const escscan: byte = $01;       backscan: byte = $0e;
  164.       ctrlscan: byte = $1d;      lshscan: byte = $2a;
  165.       capscan: byte = $3a;       f1scan: byte = $3b;
  166.       f2scan: byte = $3c;        f3scan: byte = $3d;
  167.       f4scan: byte = $3e;        f5scan: byte = $3f;
  168.       f6scan: byte = $40;        f7scan: byte = $41;
  169.       f8scan: byte = $42;        f9scan: byte = $43;
  170.       f10scan: byte = $44;       f11scan: byte = $d9;
  171.       f12scan: byte = $da;       scrlscan: byte = $46;
  172.       tabscan: byte = $0f;       entscan: byte = $1c;
  173.       rshscan: byte = $36;       prtscan: byte = $37;
  174.       altscan: byte = $38;       homescan: byte = $47;
  175.       upscan: byte = $48;        pgupscan: byte = $49;
  176.       minscan: byte = $4a;       leftscan: byte = $4b;
  177.       midscan: byte = $4c;       rightscan: byte = $4d;
  178.       plusscan: byte = $4e;      endscan: byte = $4f;
  179.       downscan: byte = $50;      pgdnscan: byte = $51;
  180.       insscan: byte = $52;       delscan: byte = $53;
  181.       numscan: byte = $45;
  182.  
  183. Is the "middle key" (the "5") on the keyboard being pressed?  Only if
  184. KeyDown[midscan] is "True".  A couple mnemonics that might not be clear:
  185.  
  186. minscan = "the minus sign on the keypad"
  187. midscan = "the middle ('5') key on the keypad"
  188. plusscan = "the plus sign on the keypad"
  189. lshscan = "the left shift key"
  190. rshscan = "the right shift key"
  191. entscan = "the enter key"
  192.  
  193. In my programs, I set up an array called "ScanOf": it's an
  194. "array[' '..'~'] of byte" that returns the scan code of a key.
  195. ("What's the scan code of 'P'?"  ScanOf['P'].  "Is '3' currently being
  196. pressed?"  Only if KeyDown[ScanOf['3']] is "True".)  Here are the
  197. values:
  198.  
  199.      * * * C O N T I N U E D   T O   N E X T   M E S S A G E * * *
  200. ---
  201.  * KingQWK 1.00 * As-Easy-As - the ONLY spreadsheet - download it today!
  202. --- FidoPCB v1.4 beta
  203.  * Origin: PC-OHIO - The Best BBS in America (pcohio.com) (1:157/200)
  204.  
  205. ─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  206. Msg  : 429 of 474                                                               
  207. From : Lou Duchez                          1:157/200.0          21 Jun 93  21:50 
  208. To   : Ian Lin                                                                   
  209. Subj : Using esc key         {3}                                              
  210. ────────────────────────────────────────────────────────────────────────────────
  211. ** CONTINUED FROM A COUPLE MESSAGES AGO -- SCAN CODES!!
  212.  
  213.   scanof['!'] := $02;  scanof['1'] := $02;
  214.   scanof['@'] := $03;  scanof['2'] := $03;
  215.   scanof['#'] := $04;  scanof['3'] := $04;
  216.   scanof['$'] := $05;  scanof['4'] := $05;
  217.   scanof['%'] := $06;  scanof['5'] := $06;
  218.   scanof['^'] := $07;  scanof['6'] := $07;
  219.   scanof['&'] := $08;  scanof['7'] := $08;
  220.   scanof['*'] := $09;  scanof['8'] := $09;
  221.   scanof['('] := $0a;  scanof['9'] := $0a;
  222.   scanof[')'] := $0b;  scanof['0'] := $0b;
  223.   scanof['_'] := $0c;  scanof['-'] := $0c;
  224.   scanof['+'] := $0d;  scanof['='] := $0d;
  225.   scanof['Q'] := $10;  scanof['q'] := $10;
  226.   scanof['W'] := $11;  scanof['w'] := $11;
  227.   scanof['E'] := $12;  scanof['e'] := $12;
  228.   scanof['R'] := $13;  scanof['r'] := $13;
  229.   scanof['T'] := $14;  scanof['t'] := $14;
  230.   scanof['Y'] := $15;  scanof['y'] := $15;
  231.   scanof['U'] := $16;  scanof['u'] := $16;
  232.   scanof['I'] := $17;  scanof['i'] := $17;
  233.   scanof['O'] := $18;  scanof['o'] := $18;
  234.   scanof['P'] := $19;  scanof['p'] := $19;
  235.   scanof['{'] := $1a;  scanof['['] := $1a;
  236.   scanof['}'] := $1b;  scanof[']'] := $1b;
  237.   scanof['A'] := $1e;  scanof['a'] := $1e;
  238.   scanof['S'] := $1f;  scanof['s'] := $1f;
  239.   scanof['D'] := $20;  scanof['d'] := $20;
  240.   scanof['F'] := $21;  scanof['f'] := $21;
  241.   scanof['G'] := $22;  scanof['g'] := $22;
  242.   scanof['H'] := $23;  scanof['h'] := $23;
  243.   scanof['J'] := $24;  scanof['j'] := $24;
  244.   scanof['K'] := $25;  scanof['k'] := $25;
  245.   scanof['L'] := $26;  scanof['l'] := $26;
  246.   scanof[':'] := $27;  scanof[';'] := $27;
  247.   scanof['"'] := $28;  scanof[''''] := $28;
  248.   scanof['~'] := $29;  scanof['`'] := $29;
  249.   scanof['|'] := $2b;  scanof['\'] := $2b;
  250.   scanof['Z'] := $2c;  scanof['z'] := $2c;
  251.   scanof['X'] := $2d;  scanof['x'] := $2d;
  252.   scanof['C'] := $2e;  scanof['c'] := $2e;
  253.   scanof['V'] := $2f;  scanof['v'] := $2f;
  254.   scanof['B'] := $30;  scanof['b'] := $30;
  255.   scanof['N'] := $31;  scanof['n'] := $31;
  256.   scanof['M'] := $32;  scanof['m'] := $32;
  257.   scanof['<'] := $33;  scanof[','] := $33;
  258.   scanof['>'] := $34;  scanof['.'] := $34;
  259.   scanof['?'] := $35;  scanof['/'] := $35;
  260.   scanof[' '] := $39;
  261.  
  262. I hope I have managed to explain this well -- I never can tell.  But it
  263. does work, and I hope you enjoy it.  I'd be eager for feedback; I intend
  264. to keep posting this whenever anyone has questions about the keyboard,
  265. and I want it to be as clear as possible.  (And all of you out there:
  266. if you think this message will help someone else, feel free to repost it
  267. at will!)
  268. ---
  269.  * KingQWK 1.00 * As-Easy-As - the ONLY spreadsheet - download it today!
  270. --- FidoPCB v1.4 beta
  271.  * Origin: PC-OHIO - The Best BBS in America (pcohio.com) (1:157/200)
  272.  
  273.